package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.vo.TreeSelect;
import com.ruoyi.system.mapper.MenuMapper;
import com.ruoyi.system.mapper.RoleMapper;
import com.ruoyi.system.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class IMenuServiceImpl extends ServiceImpl<MenuMapper,SysMenu> implements IMenuService {
    @Autowired
    private RoleMapper roleMapper;

    @Override
    public List<SysMenu> selectMenuList(SysMenu menu,Long userId) {
        List<SysMenu> menuList = null;
        // 管理员显示所有菜单信息
        if (SysUser.isAdmin(userId))
        {
            menuList = baseMapper.selectMenuList(menu);
        }
        else
        {
            menu.getParams().put("userId", userId);
            menuList = baseMapper.selectMenuListByUserId(menu);
        }
        return menuList;
    }

    @Override
    public List<SysMenu> selectMenuList(Long userId) {
        SysMenu menu = new SysMenu();
        List<SysMenu> menuList = null;
        // 管理员显示所有菜单信息
        if (SysUser.isAdmin(userId))
        {
            menuList = baseMapper.selectMenuList(menu);
        }
        else
        {
            menu.getParams().put("userId", userId);
            menuList = baseMapper.selectMenuListByUserId(menu);
        }
        return menuList;
    }

    @Override
    public Object selectMenuListByRoleId(Long roleId) {
        SysRole sysRole = roleMapper.selectById(roleId);
        return baseMapper.selectMenuListByRoleId(roleId, sysRole.isMenuCheckStrictly());
    }

    @Override
    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
        //表示要构建菜单树的菜单列表。
        List<SysMenu> menuTrees = buildMenuTree(menus);
        return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    public List<SysMenu> buildMenuTree(List<SysMenu> menus)
    {
        //用一个空列表存储菜单树
        List<SysMenu> returnList = new ArrayList<SysMenu>();
        //临时列表为了存储MenuId
        List<Long> tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
        //使用迭代器遍历 menus 列表中的每个菜单
        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
        {
            SysMenu menu = (SysMenu) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(menu.getParentId()))
            {
                recursionFn(menus, menu);
                // 添加到返回结果集
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list 分类表
     * @param t 子节点
     */
    private void recursionFn(List<SysMenu> list, SysMenu t)
    {
        // 得到子节点列表
        List<SysMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenu tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }
    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysMenu> list, SysMenu t)
    {
        return getChildList(list, t).size() > 0;
    }
    /**
     * 得到子节点列表
     */
    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
    {
        List<SysMenu> tlist = new ArrayList<SysMenu>();
        Iterator<SysMenu> it = list.iterator();
        while (it.hasNext())
        {
            SysMenu n = (SysMenu) it.next();
            if (n.getParentId().longValue() == t.getMenuId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

}
